<style lang="scss" scoped>
.xjw-popup {
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  overflow: hidden;
  z-index: 9;
  .xjw-popup_content {
    width: 100%;
    background: #ffffff;
    z-index: 1;
    display: flex;
    flex-direction: column;
    position: fixed;
    &--bottom {
      bottom: 0;
      left: 0;
      transform: translate3D(0, 100%, 0);
    }
    &--left {
      left: 0;
      top: 0;
      transform: translate3D(-100%, 0, 0);
    }
    &--right {
      right: 0;
      top: 0;
      transform: translate3D(100%, 0, 0);
    }
    &--top {
      right: 0;
      top: 0;
      transform: translate3D(0, -100%, 0);
    }
    &--center {
      left: 50%;
      top: 50%;
      transform: translate3D(-50%, -50%, 0) scale(1.2);
      opacity: 0;
    }
    &--center--show {
      transform: translate3D(-50%, -50%, 0) scale(1);
      opacity: 1;
    }
    &--show {
      transform: translate3D(0, 0, 0);
    }
  }
}
</style>
<template>
  <view class="xjw-popup" v-if="visible" :style="{ 'z-index': zIndex }">
    <xjw-mask
      :show="showPop && showMask"
      :duration="duration"
      :is-mask-hide="isMaskHide && showMask"
      @maskClick="maskClick"
      :zIndex="zIndex"
    />
    <view
      class="xjw-popup_content"
      :class="[popClass, 'xjw-popup_content--' + mode]"
      :style="[popStyle, userStyle]"
      @touchmove.stop.prevent="() => {}"
    >
      <slot></slot>
    </view>
  </view>
</template>

<script lang="ts">
import Vue, { PropType } from "vue";
import { Component, Prop, Watch } from "vue-property-decorator";
import { addUnit } from "../lib/function/index";

type TDirection = "top" | "left" | "right" | "bottom" | "center";

@Component
export default class Index extends Vue {
  @Prop({ type: Boolean, default: false }) value;
  @Prop({ type: [Number, String] }) height;
  @Prop({ type: [String, Number], default: "auto" }) width;
  @Prop({ type: [Number, String], default: 200 }) duration;
  @Prop({ type: Boolean, default: true }) isMaskHide;
  @Prop({ type: Boolean, default: true }) isPopup;
  @Prop({ type: Object, default: () => {} }) userStyle;
  @Prop({ type: String as PropType<TDirection>, default: "bottom" }) mode;
  @Prop({ type: Boolean, default: true }) showMask;
  @Prop({ type: Number, default: 2000 }) zIndex;
  @Prop({ type: Boolean, default: true }) toPx;

  visible: Boolean = false;
  showPop: Boolean = false;
  closeFromInner: Boolean = false;

  get popClass() {
    if (this.showPop) {
      return this.mode === "center"
        ? "xjw-popup_content--center--show"
        : "xjw-popup_content--show";
    }
    return "";
  }

  get popStyle() {
    return {
      width: this.width ? addUnit(this.width, this.toPx) : "auto",
      height: this.height ? addUnit(this.height, this.toPx) : "auto",
      transition: `all ${this.duration / 1000}s linear`,
      "z-index": this.zIndex,
    };
  }

  @Watch("value")
  WatchValue(val) {
    if (val) {
      this.open();
    } else if (!this.closeFromInner) {
      this.close();
    }
    this.closeFromInner = false;
  }

  mounted() {
    this.value && this.open();
  }

  maskClick() {
    this.close();
  }

  open() {
    this.change("visible", "showPop", true);
  }

  close() {
    this.closeFromInner = true;
    this.change("showPop", "visible", false);
  }

  change(field: string, field1, flag: boolean) {
    this[field] = flag;

    if (flag) {
      this.$nextTick(() => {
        setTimeout(() => {
          this[field1] = flag;
          if (this.isPopup) {
            this.$emit("input", flag);
          }
          this.$emit("open");
        }, 40);
      });
    } else {
      setTimeout(() => {
        this[field1] = flag;
        if (this.isPopup) {
          this.$emit("input", flag);
        }
        this.$emit("close");
      }, this.duration);
    }
  }
}
</script>
